namespace OpenComposite.SOBADesigner
{
	using System;
	using System.ComponentModel;
	using System.Diagnostics;
	using System.Drawing.Design;
	using System.IO;
	using System.Reflection;
	using System.Windows.Forms;
	using OpenComposite.Base;
	using OpenComposite.Forms;
	using OpenComposite.Repository.Interfaces;
	using OpenComposite.Repository.TFS;
	using OpenComposite.UserAccess;
	using OpenComposite.EII;
	using OpenComposite.EII.Forms;
	using OpenComposite.EII.Repository;
	using OpenComposite.EII.Services;
	using WeifenLuo.WinFormsUI.Docking;
	using OpenComposite.Main.Properties;

	internal partial class FormMain : Form, IStatusService
	{
		#region Initialization

		public FormMain()
		{
			InitializeComponent();

			init();
		}

		#endregion Initialization

		#region Public Members

		#region Properties

		public string AssemblyCopyright
		{
			get
			{
				// Get all Copyright attributes on this assembly
				object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
				// If there aren't any Copyright attributes, return an empty string
				if ( attributes.Length == 0 ) return "";
				// If there is a Copyright attribute, return its value
				return ( (AssemblyCopyrightAttribute)attributes[0] ).Copyright;
			}
		}

		public string EvaluationMessage
		{
			get { return _evaluationMsg; }
			set { _evaluationMsg = value; }
		}

		public bool IsLogout
		{
			get { return _logout; }
		}

		public RepositoryService RepositoryService
		{
			get { return (RepositoryService)_surfaceManager.GetService(typeof(RepositoryService)); }
		}

		#endregion Properties

		#endregion Public Members

		#region Private Members

		#region Fields

		private bool _bNewOrg = false;
		private ComponentDesignerController _controller;
		private string _evaluationMsg = null;
		private bool _logout = false;
		//private ServiceConfigurator.ConfigurationMain _serviceConfiguration = null;
		private RepositorySurfaceManager _surfaceManager;
		private System.Timers.Timer _timerLogInRefresh;
		private FormPDFViewer pdf;

		#endregion Fields

		#region Event Handlers

		private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
		{
			if ( Global.CurrentUser != null ) {
				Global.UserAccess.LogOut(Global.CurrentUser, Helper.DesignerApplicationId);
			}
		}

		private void FormMain_KeyUp(object sender, KeyEventArgs e)
		{
			if ( e.Control && e.Shift && e.KeyCode == Keys.Q ) {
				Global.Data.RepositoryService.CloseAllControllers(null);
			} else if ( e.KeyCode == Keys.F3 ) {
				searchRepository();
			}
		}

		private void FormMain_Load(object sender, EventArgs e)
		{
			this.Refresh();
			try {
				_logout = false;

				string productname = this.ProductName;
				string subtitle = this.AssemblyCopyright;

				this.Text = productname;
				this.Show();
				this.Refresh();
				if ( !string.IsNullOrEmpty(this.EvaluationMessage) ) {
					subtitle += Environment.NewLine + this.EvaluationMessage;
				}
				string version = string.Format("V {0}", Assembly.GetExecutingAssembly().GetName().Version.ToString());
				if ( Global.Initialize(_surfaceManager, this, productname, subtitle, version) ) {
					startMainProgram();
				} else {
					this.Close();
				}
			} catch ( Exception ex ) {
				Helper.ShowException(ex);
			}
		}

		private void FormMain_Shown(object sender, EventArgs e)
		{
			try {
				// required to throw an Application_ThreadException (see Program.cs) if tfs is not available
				TeamFoundationWrapper.CheckForTfs();
			} catch ( Exception ex ) {
				Debug.WriteLine(ex.ToString());
			}
		}

		private void _timerLogInRefresh_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
		{
			try {
				Global.UserAccess.RefreshLogIn(Global.CurrentUser, Helper.DesignerApplicationId);
			} catch ( Exception ex ) {
				ErrorBox.Show(ex, true);
			}
			_timerLogInRefresh.Start();
		}

		private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			showAbout();
		}

		private void exitToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.Close();
			_logout = false;
		}

		private void formOrgDesigner_Disposed(object sender, EventArgs e)
		{
			if ( _bNewOrg ) {
				_bNewOrg = false;
				try {
					FormOrgDesigner form = findChildForm<FormOrgDesigner>();
					this.Close();
					_logout = true;
					return;
					//}
				} catch ( Exception ex ) {
					Helper.ShowException("Sorry, error while trying to login.", ex);
					this.Close();
					_logout = true;
					return;
				}
			}
		}

		private void helpToolStripButton_Click(object sender, EventArgs e)
		{
			showAbout();
		}

		private void logoutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			logout();
		}

		private void miOrgDesigner_Click(object sender, EventArgs e)
		{
			openOrgDesigner();
		}

		private void miUpdateConfig_Click(object sender, EventArgs e)
		{
			showUpdateConfig();
		}

		private void pdf_DockStateChanged(object sender, EventArgs e)
		{
			this.Refresh();
		}

		private void pdf_FormClosed(object sender, FormClosedEventArgs e)
		{
			try {
				pdf.DockStateChanged -= new EventHandler(pdf_DockStateChanged);
				pdf.FormClosed -= new FormClosedEventHandler(pdf_FormClosed);
				pdf.Dispose();
				pdf = null;
				GC.Collect();
			} catch { }
		}

		private void searchRepositoryToolStripMenuItem_Click(object sender, EventArgs e)
		{
			searchRepository();
		}

		private void serviceToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ProcessStartInfo info = new ProcessStartInfo("ServiceConfigurator.exe");
			info.Verb = "runas";
			Process.Start(info);
		}

		private void setDocumentationToolStripMenuItem_Click(object sender, EventArgs e)
		{
#if DEBUG
			RepositoryService repsvc = (RepositoryService)_surfaceManager.GetService(typeof(RepositoryService));
			if ( repsvc != null && Global.Status.CurrentRepositoryId > 0 ) {
				RepositoryObject r = repsvc.GetItem<RepositoryObject>(Global.Status.CurrentRepositoryId);
				if ( r != null ) {
					OpenFileDialog dlg = new OpenFileDialog();
					dlg.Filter = "pdf|*.pdf";
					if ( dlg.ShowDialog() != DialogResult.OK ) return;

					Documentation doc = repsvc.GetItem<Documentation>(r.ExtendedProperties.DocumentationID);
					if ( doc == null ) {
						IRepositoryItem parent = null;
						doc = repsvc.GetNewItem<Documentation>(false, ref parent);
						doc.Name = "Complete Documentation";
					}
					doc.BinaryDocument = File.ReadAllBytes(dlg.FileName);
					doc.Save();
					r.ExtendedProperties.DocumentationID = doc.ID;
					r.Save();
				}
			}
#endif
		}

		private void toolboxToolStripMenuItem_Click(object sender, EventArgs e)
		{
			MainToolboxService mts =
				this.GetService(typeof(IToolboxService)) as MainToolboxService;
			if ( mts != null ) {
				mts.Show();
			}
		}

		private void useProfessionalStyleToolStripMenuItem_Click(object sender, EventArgs e)
		{
			setRenderStyle(true);
		}

		private void useSystemColorsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			setRenderStyle(false);
		}

		private void viewDocumentationToolStripMenuItem_Click(object sender, EventArgs e)
		{
			string fileName = "OpenCompositeUserGuide.pdf";
			if ( File.Exists(fileName) ) {
				Process.Start(fileName);
			} else {
				MessageBox.Show("Documentation was not found!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			return;
			#region Not used (show pdf with internal view)
			//using ( new WaitMouse() ) {
			//    try {
			//        RepositoryService repsvc = (RepositoryService)_surfaceManager.GetService(typeof(RepositoryService));
			//        if ( repsvc != null && Global.Status.CurrentRepositoryId > 0 ) {
			//            Repository r = repsvc.GetItem<Repository>(Global.Status.CurrentRepositoryId);
			//            if ( r != null ) {
			//                Documentation doc = repsvc.GetItem<Documentation>(r.ExtendedProperties.DocumentationID);
			//                if ( doc != null ) {
			//                    if ( string.IsNullOrEmpty(doc.Description) ) {
			//                        doc.Description = "PDF";
			//                        doc.Save();
			//                    }
			//                    string tmppath = Path.GetTempFileName();
			//                    File.WriteAllBytes(tmppath, doc.BinaryDocument);

			//                    pdf = new FormPDFViewer(_surfaceManager);
			//                    pdf.VisibleChanged += new EventHandler(pdf_VisibleChanged);
			//                    pdf.DockStateChanged += new EventHandler(pdf_DockStateChanged);
			//                    pdf.FormClosed += new FormClosedEventHandler(pdf_FormClosed);
			//                    pdf.Documentation = doc;
			//                    pdf.Show(dockPanelMain, DockState.Document);
			//                } else {
			//                    MessageBox.Show("Documentation not available!");
			//                }
			//            }
			//        }
			//    } catch ( System.Runtime.InteropServices.COMException ) {
			//        MessageBox.Show("Could not show documentation. Please install Adobe Reader.",
			//            "Show Documentation", MessageBoxButtons.OK, MessageBoxIcon.Error);
			//    } catch ( TimeoutException timeout ) {
			//        MessageBox.Show(string.Format("{1}{0}Please try again. If you still encounter this problem set the timeout to a higher value and try again.", Environment.NewLine, timeout.Message),
			//            "Timeout", MessageBoxButtons.OK, MessageBoxIcon.Error);
			//    } catch ( Exception ex ) {
			//        MessageBox.Show(ex.Message);
			//    }
			//}
			#endregion
		}

		private void processMonitorToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Global.Repository.RunTrackingMonitor();
		}

		#endregion Event Handlers

		#region Methods

		private void checkToolStripButton(ToolStripButton tsbtn)
		{
			this.SuspendLayout();
			foreach ( ToolStripItem tsitem in tsbtn.Owner.Items ) {
				if ( tsitem == tsbtn )
					tsbtn.Checked = !tsbtn.Checked;
				else if ( tsitem is ToolStripButton )
					( (ToolStripButton)tsitem ).Checked = false;
			}
			this.ResumeLayout(true);
		}

		private FormOrgDesigner createFormOrgDesigner()
		{
			Organization currentOrg = Global.Data.GetOrganisationById(Global.CurrentUser.OrganizationID);
			FormOrgDesigner form = new FormOrgDesigner(_surfaceManager, currentOrg);

			if ( !_bNewOrg && dockPanelMain.DocumentStyle == DocumentStyle.SystemMdi )
				form.MdiParent = this;

			form.Disposed += new EventHandler(formOrgDesigner_Disposed);
			return form;
		}

		private T findChildForm<T>()
			where T : class
		{
			if ( dockPanelMain.DocumentStyle == DocumentStyle.SystemMdi ) {
				foreach ( Form form in MdiChildren ) {
					T f = form as T;
					if ( f != null ) return f;
				}
			} else {
				DockContentCollection docs = dockPanelMain.Contents;
				foreach ( IDockContent content in docs ) {
					T c = content as T;
					if ( c != null ) return c;
				}
			}
			return null;
		}

		private void init()
		{
			// init visual styles
			OpenComposite.Base.Static.RENDERER_VS2005.RoundedEdges = false;
			ToolStripManager.Renderer = OpenComposite.Base.Static.RENDERER_VS2005;

			this.SetStyle(ControlStyles.ResizeRedraw, false);
			this.UpdateStyles();

			// _surfaceManager
			_surfaceManager = new RepositorySurfaceManager();

#if DEBUG
			setDocumentationToolStripMenuItem.Visible = true;
			setDocumentationToolStripMenuItem.Enabled = true;
#else
			setDocumentationToolStripMenuItem.Visible = false;
			setDocumentationToolStripMenuItem.Enabled = false;
#endif

			dockPanelMain.DockBottomPortion = 0.3;
			dockPanelMain.DockLeftPortion = 0.2;
			dockPanelMain.DockRightPortion = 0.2;
			dockPanelMain.DockTopPortion = 0.2;

			// initialize Login Refresh timer
			_timerLogInRefresh = new System.Timers.Timer(UserAccessController.InactiveMinutes * 60000);
			_timerLogInRefresh.AutoReset = false;
			_timerLogInRefresh.Elapsed += new System.Timers.ElapsedEventHandler(_timerLogInRefresh_Elapsed);
		}

		private void initMain()
		{
			// set repository mode
			this.RepositoryService.Mode = OpenComposite.EII.RepositoryService.RepositoryMode.CompositeDesigner;

			// show controller
			_controller = new ComponentDesignerController(dockPanelMain, _surfaceManager);
			_controller.Show();

			_surfaceManager.AddService(typeof(DataAccess), Global.Data);
			_surfaceManager.AddService(typeof(IStatusService), this);

			searchRepositoryToolStripMenuItem.Enabled = true;
		}

		private void logout()
		{
			this.Close();
			_logout = true;
			_timerLogInRefresh.Stop();
		}

		private void openOrgDesigner()
		{
			this.Cursor = Cursors.WaitCursor;
			this.Refresh();
			FormOrgDesigner form = findChildForm<FormOrgDesigner>();

			if ( form == null )
				form = createFormOrgDesigner();

			this.Refresh();
			if ( dockPanelMain.DocumentStyle == DocumentStyle.SystemMdi ) {
				form.Show();
			} else {
				form.Show(dockPanelMain);
			}
			this.Refresh();
			form.BringToFront();

			if ( _bNewOrg ) {
				form.ShowFrmNewOrg();
			}

			this.Refresh();
			this.Cursor = Cursors.Default;
			this.Refresh();
		}

		private void searchRepository()
		{
			FormSearchRepository search = findChildForm<FormSearchRepository>();
			if ( search == null ) {
				search = new FormSearchRepository(RepositoryService);
			}
			search.Show(dockPanelMain);
			search.BringToFront();
		}

		private void setProfessionalRenderer()
		{
			OpenComposite.Base.Static.RENDERER_VS2005.ColorTable.UseSystemColors = useSystemColorsToolStripMenuItem.Checked;
			OpenComposite.Base.Static.RENDERER_VS2005.RoundedEdges = false;
			ToolStripManager.Renderer = OpenComposite.Base.Static.RENDERER_VS2005;
		}

		private void setRenderStyle(bool isProfessional)
		{
			useSystemColorsToolStripMenuItem.Checked = !isProfessional;
			useProfessionalStyleToolStripMenuItem.Checked = isProfessional;
			if ( isProfessional ) {
				setProfessionalRenderer();
			} else {
				setSystemRenderer();
			}
		}

		private void setSystemRenderer()
		{
			ToolStripManager.RenderMode = ToolStripManagerRenderMode.System;
		}

		private void showAbout()
		{
			AboutBoxMain about = new AboutBoxMain();
			about.ShowDialog();
		}

		private void showUpdateConfig()
		{
			this.Cursor = Cursors.WaitCursor;
			this.Refresh();
			FormUpdateConfigurations form = findChildForm<FormUpdateConfigurations>();
			if ( form == null ) form = new FormUpdateConfigurations();
			this.Refresh();
			if ( dockPanelMain.DocumentStyle == DocumentStyle.SystemMdi ) {
				form.Show();
			} else {
				form.Show(dockPanelMain);
			}
			form.BringToFront();
			this.Cursor = Cursors.Default;
			this.Refresh();
		}

		private void startMainProgram()
		{
			try {
				if ( Global.CurrentUser != null && Global.CurrentUser.ReturnCode.Equals("OK") ) {
					// show login informations
					statusServer.Text = "Server: " + Global.Data.DBConnection.DataSource;
					statusDB.Text = "DB: " + Global.Data.DBConnection.Database;
					statusOrg.Text = "Org: " + Global.CurrentUser.OrganizationName;
					statusUser.Text = "User: " + Global.CurrentUser.FullName;

					if ( Global.CurrentUser.IsSystemAdministrator && Global.CurrentUser.OrganizationName.ToLower() == "master" ) {   // user has logged in as system administrator of the master org
						// so we start the org designer and give him the possibility to create a new org
						try {
							Helper.ShowInfo("You have logged in as system administrator of the Master organization." + Environment.NewLine +
								"You can now create a new Organziation.");
							//NewPasswordForm form = new NewPasswordForm();
							//string hashedStanard = "H7Cr2ILhAMBjSsBjARzqggm0Fjb2owjgZ4CSXIohdBkQvwarp5QOBVWVE92f//uh7j7yzcIkAWdxwPdTCQeF3g==";
							//string pass = Global.Data.UserAccess.();
							//if ( pass == hashedStanard ) {
							//    DialogResult result;
							//    do {
							//        result = form.ShowDialog(this);
							//    }
							//    while ( result != DialogResult.OK || form.Password == hashedStanard );
							//    Global.Data.UserAccess.UpdateUserPassword(form.Password);
							//}
							_bNewOrg = true;
							openOrgDesigner();
						} catch ( Exception ex ) {
							Helper.ShowException(ex);
						}
						return;
					} else {
						this.Show();
						initMain();
						Helpers.DeleteTemp();
						this.Refresh();
						_timerLogInRefresh.Start();
					}
				} else {
					this.Close();
					return;
				}
			} catch ( Exception ex ) {
				Helper.ShowException(ex);
			}
		}

		#endregion Methods

		#endregion Private Members

		#region IStatusService Members

		public void SetStatusText(string text)
		{
			tslblStatus.Text = text;
			tslblStatus.Visible = true;
		}

		public void ClearStatusText()
		{
			tslblStatus.Text = "";
			tslblStatus.Visible = false;
		}

		public void SetProgress(int minValue, int maxValue, int currentValue)
		{
			tsprogressbar.Maximum = maxValue;
			tsprogressbar.Minimum = minValue;
			tsprogressbar.Value = currentValue;
			tsprogressbar.Visible = true;
		}

		public void ClearProgress()
		{
			tsprogressbar.Maximum = 100;
			tsprogressbar.Minimum = 0;
			tsprogressbar.Value = 0;
			tsprogressbar.Visible = false;
		}

		#endregion
	}
}